using CefSharp.OffScreen;
using CefSharp;
using System.Text.RegularExpressions;
using System.Drawing;
using CefSharp.Handler;

namespace Web_rongmeiti_sys.PublishToRongMeiTi
{
    /// <summary>
    /// 登录处理
    /// </summary>
    /// 创建时间：2023-5-23 10:23:54。创建人：王浩力
    public class LoginHandler
    {
        static LoginHandler()
        {
            /* 异常情况：
            Cef.Initialize can only be called once per process. This is a limitation of the underlying CEF/Chromium framework.
            You can change many (not all) settings at runtime through RequestContext.SetPreference. 
            See https://github.com/cefsharp/CefSharp/wiki/General-Usage#request-context-browser-isolation 
            Use Cef.IsInitialized to check if Cef.Initialize has already been called to avoid this exception. 
            If you are seeing this unexpectedly then you are likely calling Cef.Initialize after
            you've created an instance of ChromiumWebBrowser, it must be called before the first instance is created.
            */
            try
            {
                //v114.2.100 第一版使用这个，此版本不支持windows server 2012 R2；
                //v109.1.110 是支持 Windows 7、Windows 8/8.1、Windows Server 2012、Windows Server 2012 R2 最后一个版本
                //当前使用v109.1.110
                //初始化Cef.Initialize在同一线程中，只准执行一次，否则报错
                var cefSettingOp = new CefSettings()
                {
                    CookieableSchemesExcludeDefaults = false,
                    PersistSessionCookies = true,
                    //WindowlessRenderingEnabled = true,
                };
#if DEBUG

                //http://localhost:9080  本地调试窗口
                cefSettingOp.RemoteDebuggingPort = 9080;
#endif
                Cef.Initialize(cefSettingOp, performDependencyCheck: true, browserProcessHandler: null);

            }
            catch (Exception ex)
            {
                var ex1 = ex.InnerException ?? ex;
                LogHelpter.AddLog("Cef.Initialize()异常" + ex1.Message, null, "LoginHandler_error");
            }
        }

        /// <summary>
        ///  验证码获取，模拟登录
        /// </summary>
        /// 创建时间：2023-6-21 16:16:43，王浩力
        public static Result LoginCall(string account, string password)
        {
            //移除cookie缓存；添加时间：2023-8-3 15:09:24，
            string cacheKey = account + "700";
            System.Runtime.Caching.MemoryCache.Default.Remove(cacheKey);

            //先删除历史的cookie文件，创建时间：2023-7-17 13:42:26 ，
            string dir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "identity_cookie");
            string filePath = Path.Combine(dir, $"cookieValue_{account}.txt");
            if (File.Exists(filePath))
            {
                File.Delete(filePath);
            }

            cookieSb.Clear();

            //1.账号密码登录，
            //2.验证码图形识别
            //string url = "https://xx.xxx.com/login.html";
            string url = MyConfigReader.GetConfigValue("iam_login_url");

            ChromiumWebBrowser webBrowser = new ChromiumWebBrowser(url)
            {
                RequestHandler = new MyRequestHandler() { Cnpc_account = account }
                //ResourceRequestHandlerFactory = new ResourceRequestHandler3()
            };

            webBrowser.FrameLoadEnd += WebBrowser_FrameLoadEnd;
            //webBrowser.AddressChanged += WebBrowser_AddressChanged;

            //等待内容完成加载
            webBrowser.WaitForInitialLoadAsync().Wait();
            //Task.Delay(500).Wait();

            //tab切换到账号登录
            //$("li[data-name=accountLogin]").click();
            var taskTabJs = webBrowser.GetMainFrame().EvaluateScriptAsync("$(\"li[data-name=accountLogin]\").click();");
            taskTabJs.Wait();
            Task.Delay(500).Wait();

            //点击触发生成验证码图片,执行页面中的js函数loadverifyimg()
            //webBrowser.GetMainFrame().EvaluateScriptAsync("loadverifyimg()").Wait();

            //获取验证码图片url
            //$("img.checkImage").attr("src")
            var jsResponse = webBrowser.GetMainFrame().EvaluateScriptAsync("$(\"img.checkImage\").attr(\"src\")");
            jsResponse.Wait();

            JavascriptResponse javascriptResponse = jsResponse.Result;
            if (!javascriptResponse.Success || javascriptResponse.Result is null || string.IsNullOrWhiteSpace(javascriptResponse.Result.ToString()))
            {
                LogHelpter.AddLog("没有获取到验证码图片url", null, "jsError");
                return new Result("登录失败");
            }

            ////获取页面html
            //string html9 = webBrowser.GetSourceAsync().Result;

            //验证码图片url
            string imgVerifyUrl = javascriptResponse.Result.ToString();

            //域名
            string baseUrl = Regex.Match(url, "(https://|http://)[A-Za-z0-9.]+/").Value;
            string imgUrl = baseUrl + imgVerifyUrl;

            //下载验证码图片到本地保存
            HttpClient client = new HttpClient();
            var taskImg = client.GetByteArrayAsync(imgUrl);
            taskImg.Wait();
            string imgDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "imgVerify", DateTime.Now.ToString("yyyyMM"));
            if (!System.IO.Directory.Exists(imgDir))
            {
                System.IO.Directory.CreateDirectory(imgDir);
            }

            string fileNameImg = Path.Combine(imgDir, DateTime.Now.Ticks + ".jpg");
            //File.WriteAllBytes(fileNameImg, taskImg.Result);
            byte[] imageBytes = taskImg.Result;

            //保存验证码图片到本地.jpg
            using (MemoryStream ms = new MemoryStream(imageBytes, 0, imageBytes.Length))
            {
                ms.Write(imageBytes, 0, imageBytes.Length);
                var img = Image.FromStream(ms, true);
                img.Save(fileNameImg, System.Drawing.Imaging.ImageFormat.Jpeg);
            }

            //识别验证码图片
            #region 识别验证码图片
            string omcFile = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "yan_zheng_ma9988.omc");
            List<string> imgStr = CodeIdentify.action(omcFile, fileNameImg);
            if (imgStr == null)
            {
                //图片未识别的目录
                string imgUnidentified_Dir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "imgVerify_unidentified", DateTime.Now.ToString("yyyyMM"));
                if (!System.IO.Directory.Exists(imgUnidentified_Dir))
                {
                    System.IO.Directory.CreateDirectory(imgUnidentified_Dir);
                }

                //为正确识别的图片保存到指定的目录
                string imgUnidentifiedPath = Path.Combine(imgUnidentified_Dir, DateTime.Now.Ticks + ".jpg");
                File.Copy(fileNameImg, imgUnidentifiedPath, true);
                File.Delete(fileNameImg);

                //return Json(new { code = 500, msg = $"处理异常,图片=" + filePath, data = imgStr });
                LogHelpter.AddLog($"识别验证码异常,图片{fileNameImg}", null, "error_code_Img_Identify");
                return new Result("登录失败,识别验证码异常");
            }

            string input2 = string.Join("", imgStr);
            LogHelpter.AddLog($"识别验证码图片{Path.GetFileName(fileNameImg)}，识别结果{input2}", null, "Img_Identify");

            //*代表无效的字符串
            input2 = input2.Replace("*", "");

            //Replace("=","-")处理将中间-号识别为=号的情况，2023-6-29 17:47:52
            string input = input2.TrimEnd('=').Replace("=", "-");

            int num1 = 0;
            int num2 = 0;
            if (!(input2.IndexOf('-') >= 0 || input2.IndexOf('+') >= 0))
            {
                //return Json(new { code = 500, msg = $"识别失败，识别的结果{input2},图片{filePath}", data = input2 });
                LogHelpter.AddLog($"识别失败，识别的结果{input2},图片{fileNameImg}", null, "error_code_Img_Identify");
                return new Result("登录失败,验证码识别异常");
            }

            int.TryParse(input.Split(new char[] { '-', '+' })[0], out num1);
            int.TryParse(input.Split(new char[] { '-', '+' })[1], out num2);

            int result = 0;
            if (input.IndexOf("-") >= 0)
            {
                result = num1 - num2;
            }
            else if (input.IndexOf("+") >= 0)
            {
                result = num1 + num2;
            }

            #endregion

            ////模拟登录
            //string account = MyConfigReader.GetConfigValue("iam_login_account");
            //string password = MyConfigReader.GetConfigValue("iam_login_password");

            //账号、密码、验证码赋值js; 调用登录js方法
            string jsLoginWork = $"$(\"#cnpc-input-userName\").val(\"{account}\");"
                        + $"$(\"#cnpc-input-pwd\").val(\"{password}\");"
                        + $"$(\".verifyCode\").val(\"{result}\");"
                        + "userNameLogin();";

            var jsLogin = webBrowser.GetMainFrame().EvaluateScriptAsync(jsLoginWork);
            jsLogin.Wait();

            JavascriptResponse jsLoginResponse = jsLogin.Result;
            if (!jsLoginResponse.Success)
            {
                LogHelpter.AddLog("登录账号、密码赋值给输入框，登录模拟点击js", null, "jsError");
                return new Result("登录失败");
            }

            //等待url变化后，加载的新页面，登录成功后进入https://xx.xxx.com/index.html
            var navHome = webBrowser.WaitForNavigationAsync();
            navHome.Wait();

            //等待内容完成加载
            webBrowser.WaitForInitialLoadAsync().Wait();

            ////查看登录后的代码
            //string html25 = webBrowser.GetSourceAsync().Result;

            /**
            1.先请求https://xx.bb.com/会自动注册身份,
            2.再请求  https://xx.bb.com/api/Common/GetCurrentUserInfo
            将cookie写入本地Cookie，方便代码获取
            */
            //https://xx.bb.com         
            webBrowser.Load(MyConfigReader.GetConfigValue("rongmeiti_url"));

            //var jsLoginPfEip = webBrowser.GetMainFrame().EvaluateScriptAsync("window.location.href=\"https://xx.bb.com/\";");
            //jsLoginPfEip.Wait();

            //等待url变化后，加载的新页面，登录成功后进入https://xx.xxx.com/index.html
            var pf_eip_cnpcHome = webBrowser.WaitForNavigationAsync(timeout: TimeSpan.FromSeconds(30));
            pf_eip_cnpcHome.Wait();

            //等待内容完成加载
            webBrowser.WaitForInitialLoadAsync().Wait();

            //检察是否成功写了cookie文件，没有成功则一直阻塞线程，2023-6-27 16:16:28
            int check_count = 0;
            while (true)
            {
                if (check_count > 10)
                {
                    LogHelpter.AddLog("一直获取不到cookie，处理异常", null, "identityCookie_while_error");
                    return new Result("登录失败");
                }
                string? identityCookie = AuthCookieHelpter.GetIdentityCookie(account);
                if (!string.IsNullOrWhiteSpace(identityCookie))
                {
                    LogHelpter.AddLog("成功写了cookie文件，account=" + account, null, "identityCookie_while");
                    break;
                }
                LogHelpter.AddLog("检察是否成功写了cookie文件...", null, "identityCookie_while");
                check_count++;
                Thread.Sleep(1000);
            }

            return new Result("登录成功", 200);
        }

        private static void WebBrowser_AddressChanged(object? sender, AddressChangedEventArgs e)
        {
            LogHelpter.AddLog(e.Address, null, "AddressChanged");
        }

        public static System.Text.StringBuilder cookieSb = new System.Text.StringBuilder();

        private static void WebBrowser_FrameLoadEnd(object? sender, FrameLoadEndEventArgs e)
        {
            //获取谁在调用，cnpc账号
            ChromiumWebBrowser webBrowser = sender as ChromiumWebBrowser;
            var myRequestHandler = webBrowser.RequestHandler as MyRequestHandler;
            string cnpc_account = myRequestHandler.Cnpc_account;

            LogHelpter.AddLog(e.Url + " 状态=" + e.HttpStatusCode, null, "Log_FrameLoadEnd");

            var cookieManager = Cef.GetGlobalCookieManager();
            CookieVisitorHandle visitor = new CookieVisitorHandle();
            visitor.OnCookie = cookie =>
            {
                string url = cookie.Domain + cookie.Path;
                LogHelpter.AddLog($"path={url},{cookie.Name}={cookie.Value}", null, "getCookie");

                //xx.bb.com/api,.AspNetCore.CookiesC1
                //xx.bb.com/api,.AspNetCore.CookiesC2                 
                if (url == "xx.bb.com/api" && cookie.Name == ".AspNetCore.CookiesC1")
                {
                    cookieSb.Append(cookie.Name + "=" + cookie.Value + ";");
                    if (cookie.Value.Length > 0)
                    {
                        LogHelpter.AddLog("登录成功", null, "FrameLoadEnd");
                    }
                }
                if (url == "xx.bb.com/api" && cookie.Name == ".AspNetCore.CookiesC2")
                {
                    cookieSb.Append(cookie.Name + "=" + cookie.Value + ";");

                    //保存cookie到本地文件
                    AuthCookieHelpter.SaveCookie(cnpc_account, cookieSb.ToString());
                }
            };

            cookieManager.VisitAllCookies(visitor);
        }


    }
}
